home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / CUGUK / COMMS / C101.ZIP / UUPC11XS.ZIP / MAIL / DELIVER.C < prev    next >
C/C++ Source or Header  |  1992-12-18  |  38KB  |  967 lines

  1. /*--------------------------------------------------------------------*/
  2. /*    d e l i v e r  . c                                              */
  3. /*                                                                    */
  4. /*    UUPC/extended mail delivery subroutines                         */
  5. /*--------------------------------------------------------------------*/
  6.  
  7. /*--------------------------------------------------------------------*/
  8. /*    Changes Copyright (c) 1989 by Andrew H. Derbyshire.             */
  9. /*                                                                    */
  10. /*    Changes Copyright (c) 1990-1992 by Kendra Electronic            */
  11. /*    Wonderworks.                                                    */
  12. /*                                                                    */
  13. /*    All rights reserved except those explicitly granted by the      */
  14. /*    UUPC/extended license agreement.                                */
  15. /*--------------------------------------------------------------------*/
  16.  
  17. /*--------------------------------------------------------------------*/
  18. /*                          RCS Information                           */
  19. /*--------------------------------------------------------------------*/
  20.  
  21. /*
  22.  *    $Id: DELIVER.C 1.4 1992/12/18 13:05:18 ahd Exp $
  23.  *
  24.  *    $Log: DELIVER.C $
  25.  * Revision 1.4  1992/12/18  13:05:18  ahd
  26.  * Use one token on request line for UUCP
  27.  *
  28.  * Revision 1.3  1992/12/05  23:38:43  ahd
  29.  * Skip blanks as well as unprintable characters
  30.  *
  31.  * Revision 1.2  1992/12/04  01:00:27  ahd
  32.  * Add system alias support
  33.  *
  34.  */
  35.  
  36. /*--------------------------------------------------------------------*/
  37. /*    Embedded Japanese support provided by Kenji Rikitake            */
  38. /*    28-AUG-1991                                                     */
  39. /*                                                                    */
  40. /*    On Japanese support:                                            */
  41. /*                                                                    */
  42. /*    Japanese MS-DOS uses a 2byte Kanji (Japanese ideogram) code     */
  43. /*    called "Shift-JIS".  This cannot be delivered via SMTP since    */
  44. /*    Shift-JIS maps its first byte from 0x80-0x9f and 0xe0-0xfc.     */
  45. /*    JUNET requests all hosts to send Kanji in a 7bit subset of      */
  46. /*    ISO2022.  This is commonly called "JIS 7bit".                   */
  47. /*                                                                    */
  48. /*    To provide Japanese functionality, you need to convert all      */
  49. /*    remote delivery messages to JIS 7bit, and all local delivery    */
  50. /*    messages to Shift-JIS.                                          */
  51. /*--------------------------------------------------------------------*/
  52.  
  53. /*--------------------------------------------------------------------*/
  54. /*    Use a complex beep upon mail delivery if way to control the     */
  55. /*    speaker is available; if using MS C 6.0 under DOS, we can't     */
  56. /*    so don't try                                                    */
  57. /*--------------------------------------------------------------------*/
  58.  
  59. #ifdef __TURBOC__
  60. #define SMARTBEEP
  61. #endif
  62.  
  63. #ifdef FAMILYAPI
  64. #define SMARTBEEP
  65. #endif
  66.  
  67. #define INCLUDE ":include:"
  68.  
  69. /*--------------------------------------------------------------------*/
  70. /*                        System include files                        */
  71. /*--------------------------------------------------------------------*/
  72.  
  73. #include <stdio.h>
  74. #include <stdlib.h>
  75. #include <io.h>
  76. #include <ctype.h>
  77. #include <sys/types.h>
  78. #include <string.h>
  79. #include <process.h>
  80. #include <limits.h>
  81.  
  82. #ifdef __TURBOC__
  83. #include <dos.h>
  84. #endif
  85.  
  86. #ifdef FAMILYAPI
  87. #ifdef WIN32
  88. #include <windows.h>
  89. #else
  90. #include <os2.h>
  91. #endif
  92. #endif
  93.  
  94. /*--------------------------------------------------------------------*/
  95. /*                    UUPC/extended include files                     */
  96. /*--------------------------------------------------------------------*/
  97.  
  98. #include "lib.h"
  99. #include "address.h"
  100. #include "deliver.h"
  101. #include "expath.h"
  102. #include "getseq.h"
  103. #include "kanjicnv.h"
  104. #include "hlib.h"
  105. #include "hostable.h"
  106. #include "import.h"
  107. #include "pushpop.h"
  108. #include "security.h"
  109. #include "stater.h"
  110. #include "usertabl.h"
  111. #include "sysalias.h"
  112.  
  113. #ifdef SMARTBEEP
  114. #include "ssleep.h"
  115. #endif
  116.  
  117. /*--------------------------------------------------------------------*/
  118. /*        Define current file name for panic() and printerr()         */
  119. /*--------------------------------------------------------------------*/
  120.  
  121. currentfile();
  122.  
  123. /*--------------------------------------------------------------------*/
  124. /*                        Internal prototypes                         */
  125. /*--------------------------------------------------------------------*/
  126.  
  127. static size_t DeliverLocal( const char *input,  /* Input file name    */
  128.                           char *user,     /* Target address           */
  129.                           const boolean sysalias,
  130.                                              /* Already sys alias     */
  131.                           boolean validate); /* Validate/forward
  132.                                                 local mail            */
  133.  
  134. static int DeliverFile( const char *input,
  135.                         const char *mboxname,
  136.                         const long start,
  137.                         const long end,
  138.                         boolean *announce,
  139.                         struct UserTable *userp,
  140.                         const boolean sysalias,  /* Already sys alias     */
  141.                         const boolean validate );
  142.  
  143. static void trumpet( const char *tune);
  144.  
  145. static size_t DeliverRemote( const char *input, /* Input file name    */
  146.                              const char *address,  /* Target address  */
  147.                              const char *path);
  148.  
  149. static size_t DeliverGateway(   const char *input,
  150.                                 const char *user,
  151.                                 const char *node,
  152.                                 const struct HostTable *hostp);
  153.  
  154. static int CopyData(   const boolean remotedelivery,
  155.                        const char *input,
  156.                        FILE *mbox);
  157.  
  158. static char *stats( const char *fname );
  159.  
  160. /*--------------------------------------------------------------------*/
  161. /*   Global (set by rmail.c) for number of hops this mail has seen    */
  162. /*--------------------------------------------------------------------*/
  163.  
  164.  INTEGER hops = 0;
  165.  
  166.  boolean remoteMail = FALSE;
  167.  
  168.  char *ruser = NULL;
  169.  char *rnode = NULL;
  170.  char *uuser = NULL;
  171.  
  172. /*--------------------------------------------------------------------*/
  173. /*    D e l i v e r                                                   */
  174. /*                                                                    */
  175. /*    Deliver mail to one user                                        */
  176. /*--------------------------------------------------------------------*/
  177.  
  178. size_t Deliver(       const char *input,    /* Input file name       */
  179.                             char *address,  /* Target address           */
  180.                       const boolean sysalias,  /* Already sys alias     */
  181.                           boolean validate)  /* Validate/forward
  182.                                                 local mail            */
  183. {
  184.    char node[MAXADDR];
  185.    char path[MAXADDR];
  186.    char user[MAXADDR];
  187.    char *token;
  188.    struct HostTable *hostp;
  189.  
  190.    if ( strlen( address ) >= MAXADDR )
  191.    {
  192.       printmsg( 0,
  193.             "Delivering to postmaster: Excessive address length %d for %s",
  194.                strlen(address) , address );
  195.       return Deliver( input, E_postmaster, FALSE, TRUE);
  196.    }
  197.  
  198.    user_at_node(address, path, node, user);
  199.  
  200. /*--------------------------------------------------------------------*/
  201. /*                       Handle local delivery                        */
  202. /*--------------------------------------------------------------------*/
  203.  
  204.    if (equal(path, E_nodename)) /* Local node?                       */
  205.    {
  206.       struct HostTable *hostx = checkname( node );
  207.       if (hostx->hstatus == localhost)  /* Really the local node?    */
  208.          return DeliverLocal( input, user, sysalias, validate );
  209.                                  /* Yes!                             */
  210.       else {
  211.          printmsg(0,"Mail for \"%s\" via \"%s\" has no "
  212.                     "delivery route, delivering to postmaster %s",
  213.                address, path , E_postmaster);
  214.          return Deliver( input, E_postmaster, FALSE, TRUE);
  215.       } /* else */
  216.    }  /* if */
  217.  
  218. /*--------------------------------------------------------------------*/
  219. /*                    Do we need loop protection?                     */
  220. /*--------------------------------------------------------------------*/
  221.  
  222.    if (hops > E_maxhops)
  223.    {
  224.          printmsg(0,
  225.          "Mail for \"%s\" via \"%s\" has exceeded hop "
  226.          "limit of %d, delivering to postmaster %s",
  227.                address, path , E_maxhops, E_postmaster);
  228.          return Deliver( input, E_postmaster, FALSE, TRUE);
  229.    }
  230.  
  231. /*--------------------------------------------------------------------*/
  232. /*                   Deliver to a gateway if needed                   */
  233. /*--------------------------------------------------------------------*/
  234.  
  235.    hostp = checkname( path );
  236.    if ( (hostp != BADHOST) && (hostp->hstatus == gatewayed))
  237.       return DeliverGateway( input, user, node, hostp );
  238.  
  239. /*--------------------------------------------------------------------*/
  240. /*         Deliver mail to a system directory connected to us         */
  241. /*--------------------------------------------------------------------*/
  242.  
  243.    if (equal(path,node))   /* Directly connected system?          */
  244.       return DeliverRemote( input, user, path); /* Yes            */
  245.  
  246. /*--------------------------------------------------------------------*/
  247. /*   Default delivery; strip any this node and the directly           */
  248. /*   connected system from the address, then deliver to the next      */
  249. /*   hop on the route                                                 */
  250. /*--------------------------------------------------------------------*/
  251.  
  252.    strcpy(node,address);
  253.    token = strtok(node,"!");  /* Get first host in path        */
  254.    if (equal( HostAlias(token), E_nodename)) /* Local system?  */
  255.    {
  256.       token =  strtok(NULL,"");  /* Yes --> Get rest of addr   */
  257.       strcpy(address, token);    /* Use it for address         */
  258.       token = strtok(token,"!"); /* Get next host in path      */
  259.    } /* if */
  260.  
  261.    if (equal( HostAlias(token), path ))  /* Next system?       */
  262.    {
  263.       token =  strtok(NULL,"");  /* Yes --> Get rest of addr   */
  264.       strcpy(address, token);    /* Use it for address         */
  265.    } /* if */
  266.  
  267.    if (!strpbrk(address,"!@"))   /* Any host delimiters?       */
  268.    {                             /* No --> Check for % routing */
  269.       token = strrchr(address,'%'); /* Get last percent sign   */
  270.       if (token != NULL)
  271.          *token = '@';           /* Make it an RFC-822 address */
  272.       else
  273.          printmsg(0,"Deliver: Cannot find node in \"%s\"",
  274.                address);         /* That's odd, it should not  */
  275.                                  /* be a local address!        */
  276.    } /* if */
  277.  
  278.    return DeliverRemote( input, address, path );
  279.  
  280. } /* Deliver */
  281.  
  282. /*--------------------------------------------------------------------*/
  283. /*    D e l i v e r L o c a l                                         */
  284. /*                                                                    */
  285. /*    Handle local delivery, including optional forwarding            */
  286. /*--------------------------------------------------------------------*/
  287.  
  288. static size_t DeliverLocal( const char *input,
  289.                                           /* Input file name          */
  290.                           char *user,     /* Target address           */
  291.                           const boolean sysalias,
  292.                                           /* Already sys alias     */
  293.                           boolean validate)  /* TRUE = validate,
  294.                                                 forward user's mail   */
  295. {
  296.    char mboxname[FILENAME_MAX];
  297.    struct UserTable *userp = NULL;
  298.    ALIASTABLE *aliasp = NULL;
  299.    int delivered = 0;
  300.    boolean announce = FALSE;
  301.    FILE *mbox;
  302.  
  303. /*--------------------------------------------------------------------*/
  304. /*    If the parameter is the postmaster, use the configuration       */
  305. /*    defined value for the postmaster                                */
  306. /*--------------------------------------------------------------------*/
  307.  
  308.    if (equali(user, POSTMASTER))
  309.       user = E_postmaster;
  310.  
  311. /*--------------------------------------------------------------------*/
  312. /*             Validate user id and check for forwarding              */
  313. /*--------------------------------------------------------------------*/
  314.  
  315.    if (validate)
  316.    {
  317.       validate = strcmp( E_postmaster , user);
  318.                                  /* Don't loop delivering to postmast*/
  319.  
  320.       userp = checkuser(user);   /* Locate user id in host table     */
  321.  
  322. /*--------------------------------------------------------------------*/
  323. /*                     Process any system aliases                     */
  324. /*--------------------------------------------------------------------*/
  325.  
  326.       if ( ! sysalias )
  327.       {
  328.          aliasp = checkalias( user );  /* System alias?             */
  329.  
  330.          if ( aliasp != NULL )
  331.          {
  332.             delivered += DeliverFile( input,
  333.                                       SysAliases,
  334.                                       aliasp->start,
  335.                                       aliasp->end,
  336.                                       &announce ,
  337.                                       userp,
  338.                                       TRUE,
  339.                                       validate );
  340.  
  341.             if ( announce && ( userp != BADUSER ))
  342.                trumpet( userp->beep);  /* Yes --> Inform the user    */
  343.             return delivered;
  344.  
  345.          } /* if */
  346.       } /* if */
  347.  
  348. /*--------------------------------------------------------------------*/
  349. /*             No system alias, verify the user is valid              */
  350. /*--------------------------------------------------------------------*/
  351.  
  352.       if ( userp == BADUSER )    /* Invalid user id?                 */
  353.       {                          /* Yes --> Dump in trash bin        */
  354.          printmsg(0,
  355.                "\"%s\" is an invalid user, delivering to %s",
  356.                user, E_postmaster);
  357.          return DeliverLocal( input, E_postmaster, FALSE, validate);
  358.       } /* if */
  359.  
  360. /*--------------------------------------------------------------------*/
  361. /*               The user id validated; handle the mail               */
  362. /*--------------------------------------------------------------------*/
  363.  
  364.       mkfilename(mboxname, userp->homedir, DOTFORWARD);
  365.  
  366.       if (access( mboxname, 0 )) /* The .forward file exists?        */
  367.          announce = TRUE;        /* No --> Fall through              */
  368.       else {
  369.          delivered += DeliverFile( input,
  370.                                    mboxname,
  371.                                    0,
  372.                                    LONG_MAX,
  373.                                    &announce,
  374.                                    userp,
  375.                                    FALSE,
  376.                                    validate);
  377.  
  378.          if (announce)        /* Did we deliver mail locally?        */
  379.             trumpet( userp->beep);  /* Yes --> Inform the user       */
  380.          return delivered;
  381.  
  382.       } /* if */
  383.  
  384.    } /* if (validate) */
  385.  
  386. /*--------------------------------------------------------------------*/
  387. /*       The user is valid (or not validated) and not forwarded       */
  388. /*--------------------------------------------------------------------*/
  389.  
  390.    if ((*user == '/') || (isalpha( *user ) && user[1] == ':'))
  391.                               /* Absolute path from recursive call?   */
  392.       strcpy(mboxname, user); /* Yes --> Use it as-is                 */
  393.    else
  394.       mkmailbox(mboxname, user);
  395.                               /* No --> Build normal name             */
  396.  
  397.    printmsg(1,"Delivering mail %sfrom %s%s%s to %s",
  398.                         stats( input ),
  399.                         ruser,
  400.                         remoteMail ? "@" : "",
  401.                         remoteMail ? rnode : "",
  402.                          user );
  403.  
  404.    if ( announce )
  405.       trumpet( userp->beep);  /* Local delivery, inform the user     */
  406.  
  407.    mbox = FOPEN( mboxname , "a", TEXT );
  408.    if (mbox == NULL )
  409.    {
  410.       printerr(mboxname);
  411.       printmsg(0,"Cannot open mailbox \"%s\" for output",
  412.                   mboxname);
  413.       panic();
  414.    }
  415.  
  416.    if (!isatty(fileno(mbox)))
  417.       fputs(MESSAGESEP,mbox); /* Write separator line                 */
  418.  
  419.    return CopyData( FALSE, input , mbox );
  420.  
  421. } /* DeliverLocal */
  422.  
  423. /*--------------------------------------------------------------------*/
  424. /*       D e l i v e r F i l e                                        */
  425. /*                                                                    */
  426. /*       Process a local or system aliases file                       */
  427. /*--------------------------------------------------------------------*/
  428.  
  429. static int DeliverFile( const char *input,
  430.                         const char *fwrdname,
  431.                         const long start,
  432.                         const long end,
  433.                         boolean *announce,
  434.                         struct UserTable *userp,
  435.                         const boolean sysalias,  /* Already sys alias     */
  436.                         const boolean validate )
  437. {
  438.    char buf[BUFSIZ];
  439.    FILE *fwrd = FOPEN(fwrdname, "r", TEXT);
  440.    int delivered = 0;
  441.  
  442.    if ( fwrd == NULL )
  443.    {
  444.       printerr( fwrdname );
  445.       printmsg(0,"Cannot open forward file %s, delivering to %s",
  446.                fwrdname,
  447.                E_postmaster );
  448.       return DeliverLocal( input, E_postmaster, sysalias, validate );
  449.    }
  450.  
  451.    if ( start != 0 )
  452.       fseek( fwrd, start, SEEK_SET);
  453.  
  454.    while((ftell(fwrd) < end) && (fgets( buf , BUFSIZ , fwrd) != NULL ))
  455.    {
  456.       char command[BUFSIZ];
  457.       char *s = buf;
  458.       char c;
  459.       char *nextfile = NULL;
  460.  
  461.       if ( buf[ strlen(buf) - 1 ]== '\n')
  462.          buf[ strlen(buf) - 1 ] = '\0';
  463.  
  464.       while( *s && ! isgraph( *s ))    /* Trim leading white space      */
  465.          s++;
  466.  
  467.       printmsg(8,"Forwarding to \"%s\"", s);
  468.       if ( equalni( buf, INCLUDE, strlen(INCLUDE)))
  469.       {
  470.          nextfile = strtok( s + strlen(INCLUDE), WHITESPACE );
  471.          if ( nextfile == NULL )
  472.          {
  473.             printmsg(0,"%s: Missing file name after %s, "
  474.                        "delivering to %s",
  475.                         fwrdname, INCLUDE, E_postmaster );
  476.             s = E_postmaster;
  477.             c = *s;
  478.          }
  479.          else
  480.             c = ':';
  481.       } /* if */
  482.       else if ( isalpha(*s ) && (s[1] == ':'))  /* Drive name?    */
  483.          c = '/';             /* Yes --> flag as absolute path    */
  484.       else if ( *s == ':')    /* Avoid false triggers ...         */
  485.          c = ' ';             /* ... by making it general case    */
  486.       else                    /* Handle other cases in switch ... */
  487.          c = *s;
  488.  
  489.       switch(c)
  490.       {
  491.          case '#':
  492.             break;            /* Comment, ignore            */
  493.  
  494.          case '\0':
  495.             break;            /* Empty line, ignore         */
  496.  
  497.          case '|':               /* Pipe mail into a command   */
  498.          {
  499.             long here = ftell(fwrd);
  500.             fclose(fwrd);
  501.             sprintf(command , "%s < %s", &s[1], input);
  502.             printmsg(1,"Executing \"%s\" in %s",
  503.                   command, userp->homedir);
  504.             PushDir( userp->homedir );
  505.             system(command);                 /* FIX THIS */
  506.             PopDir();
  507.             delivered += 1;
  508.             fwrd = FOPEN(fwrdname, "r", TEXT);
  509.             fseek( fwrd, here, SEEK_SET);
  510.             break;
  511.          } /* case */
  512.  
  513.          case '\\':              /* Deliver without forwarding */
  514.             delivered += Deliver( input, &s[1], TRUE, FALSE );
  515.             *announce = TRUE;
  516.             break;
  517.  
  518.          case ':':
  519.             delivered += DeliverFile( input, nextfile, 0, LONG_MAX,
  520.                                       announce, userp,
  521.                                       FALSE, TRUE );
  522.             break;
  523.  
  524.          case '/':               /* Save in absolute path name */
  525.          case '~':
  526.             if (expand_path(s, NULL, userp->homedir,
  527.                             E_mailext) == NULL )
  528.             {
  529.                printmsg(0,
  530.                      "Invalid path in filename, delivering to %s",
  531.                       E_postmaster);
  532.                return DeliverLocal( input, E_postmaster,
  533.                                     sysalias, validate );
  534.             }
  535.             else
  536.                delivered += DeliverLocal( input, s, sysalias, FALSE );
  537.             *announce = TRUE;
  538.             break;
  539.  
  540.          default:                /* Deliver normally           */
  541.               delivered += Deliver( input, s, sysalias, validate );
  542.       } /* switch */
  543.    } /* while */
  544.  
  545.    fclose( fwrd );
  546.  
  547.    return delivered;
  548.  
  549. } /* DeliverFile */
  550.  
  551.  
  552. /*--------------------------------------------------------------------*/
  553. /*    t r u m p e t                                                   */
  554. /*                                                                    */
  555. /*    Trumpet the arrival of remote mail to a local user              */
  556. /*--------------------------------------------------------------------*/
  557.  
  558. static void trumpet( const char *tune)
  559. {
  560. #ifdef SMARTBEEP
  561.    char buf[BUFSIZ];
  562.    char *token = buf;
  563.    size_t tone, duration;
  564. #endif
  565.  
  566.    if ((tune == NULL) || !remoteMail) /* Should we announce?  */
  567.       return;                 /* No --> Return quietly (literally)   */
  568.  
  569. /*--------------------------------------------------------------------*/
  570. /*             We are to announce the arrival of the mail             */
  571. /*--------------------------------------------------------------------*/
  572.  
  573. #ifdef SMARTBEEP
  574.    strcpy(buf,tune);          /* Save the data                       */
  575.  
  576.    while( (token = strtok( token, ",")) != NULL)
  577.    {
  578.       tone = (size_t) atoi(token);
  579.       token = strtok( NULL, ",");
  580.       duration = (token == NULL) ? 500 : (size_t) atoi(token);
  581.  
  582. #ifdef __TURBOC__
  583.       if (tone == 0)
  584.          nosound();
  585.       else
  586.          sound( tone );
  587.       ddelay( duration );
  588. #else
  589.       if (tone == 0)
  590.          ddelay(duration);
  591.       else {
  592. #ifdef WIN32
  593.          Beep( tone, duration );
  594. #else
  595.          DosBeep( tone, duration );
  596. #endif
  597.       }
  598. #endif /* SMARTBEEP */
  599.  
  600.       token = NULL;           /* Look at next part of string   */
  601.    } /* while */
  602.  
  603. #ifdef __TURBOC__
  604.    nosound();
  605. #endif
  606. #else
  607.  
  608. /*--------------------------------------------------------------------*/
  609. /*      We cannot play the requested tune; just beep at the user      */
  610. /*--------------------------------------------------------------------*/
  611.  
  612.    fputc('\a', stdout);
  613. #endif /* SMARTBEEP */
  614.  
  615. } /* trumpet */
  616.  
  617. /*--------------------------------------------------------------------*/
  618. /*    D e l i v e r G a t e w a y                                     */
  619. /*                                                                    */
  620. /*    Deliver mail via a gateway program                              */
  621. /*--------------------------------------------------------------------*/
  622.  
  623. static size_t DeliverGateway(   const char *input,
  624.                                 const char *user,
  625.                                 const char *node,
  626.                                 const struct HostTable *hostp)
  627. {
  628.    char command[BUFSIZ];
  629.  
  630. /*--------------------------------------------------------------------*/
  631. /*    Format the command and tell the user what we're going to do     */
  632. /*--------------------------------------------------------------------*/
  633.  
  634.    sprintf(command , "%s %s %s %s < %s",
  635.                      hostp->via,          /* Program to perform forward */
  636.                      hostp->hostname,     /* Nominal host routing via   */
  637.                      node ,               /* Final destination system   */
  638.                      user,                /* user on "node" for delivery*/
  639.                      input);              /* The data to forward        */
  640.  
  641.    printmsg(1,
  642.       "Gatewaying mail %sfrom %s@%s to %s@%s via %s using \"%s\"",
  643.        stats( input ),
  644.        ruser, rnode, user, node, hostp->hostname, hostp->via);
  645.    printmsg(3,"DeliverGateway: %s",command);
  646.  
  647. /*--------------------------------------------------------------------*/
  648. /*  Run the command and return caller with count of mail delivered    */
  649. /*--------------------------------------------------------------------*/
  650.  
  651.    system(command);
  652.    return 1;
  653.  
  654. } /* DeliveryGateway */
  655.  
  656. /*--------------------------------------------------------------------*/
  657. /*    D e l i v e r R e m o t e                                       */
  658. /*                                                                    */
  659. /*    Queue mail for delivery on another system via UUCP              */
  660. /*--------------------------------------------------------------------*/
  661.  
  662. static size_t DeliverRemote( const char *input, /* Input file name    */
  663.                     const char *address,  /* Target address           */
  664.                     const char *path)
  665. {
  666.    static char *spool_fmt = SPOOLFMT;              /* spool file name */
  667.    static char *dataf_fmt = DATAFFMT;
  668.    static char *send_cmd  = "S %s %s %s - %s 0666\n";
  669.    static long seqno = 0;
  670.    static char *SavePath = NULL;
  671.    FILE *stream;              /* For writing out data                */
  672.    static char everyone[500]; /* 512, with room for "rmail "         */
  673.  
  674.    char msfile[FILENAME_MAX]; /* MS-DOS format name of files         */
  675.    char msname[22];           /* MS-DOS format w/o path name         */
  676.  
  677.    char tmfile[15];           /* Call file, UNIX format name         */
  678.    static char ixfile[15];    /* eXecute file for remote system,
  679.                                 UNIX format name for local system   */
  680.    static char idfile[15];    /* Data file, UNIX format name         */
  681.    static char rdfile[15];    /* Data file name on remote system,
  682.                                  UNIX format                         */
  683.    static char rxfile[15];    /* Remote system UNIX name of eXecute
  684.                                  file                                */
  685.  
  686.    printmsg(1,"Spooling mail %sfrom %s%s%s to %s via %s",
  687.                stats( input ),
  688.                ruser,
  689.                remoteMail ? "@" : "",
  690.                remoteMail ? rnode : "",
  691.                address ,
  692.                path);
  693.  
  694. /*--------------------------------------------------------------------*/
  695. /*          Create the UNIX format of the file names we need          */
  696. /*--------------------------------------------------------------------*/
  697.  
  698.    if ((seqno == 0) ||
  699.        (SavePath == NULL) ||
  700.        !equal(SavePath, path) ||
  701.        ((int) (strlen(everyone) + strlen(address) + 2) > (int) sizeof everyone))
  702.    {
  703.       char *seq;
  704.       seqno = getseq();
  705.       seq = JobNumber( seqno );
  706.  
  707.       if  (SavePath != NULL )
  708.       {
  709.          free(SavePath);
  710.          SavePath = NULL;
  711.       } /* if */
  712.  
  713.       sprintf(tmfile, spool_fmt, 'C', path,     'C' , seq);
  714.       sprintf(idfile, dataf_fmt, 'D', E_nodename , seq, 'd');
  715.       sprintf(rdfile, dataf_fmt, 'D', E_nodename , seq, 'r');
  716.       sprintf(ixfile, dataf_fmt, 'D', E_nodename , seq, 'e');
  717.       sprintf(rxfile, dataf_fmt, 'X', E_nodename , seq, 'r');
  718.       strcpy(everyone,address);
  719.  
  720.    } /* if */
  721.    else {
  722.       strcat(everyone," ");
  723.       strcat(everyone,address);
  724.    } /* else */
  725.  
  726. /*--------------------------------------------------------------------*/
  727. /*                     create remote X (xqt) file                     */
  728. /*--------------------------------------------------------------------*/
  729.  
  730.    importpath( msname, ixfile, path);
  731.    mkfilename( msfile, E_spooldir, msname);
  732.  
  733.    stream = FOPEN(msfile, "w", BINARY);
  734.    if ( stream == NULL )
  735.    {
  736.       printerr(msfile);
  737.       printmsg(0, "DeliverRemote: cannot open X file %s", msfile);
  738.       return 0;
  739.    } /* if */
  740.  
  741.  
  742.    fprintf(stream, "R %s@%s\nU %s %s\nF %s\nI %s\nC rmail %s\n",
  743.                ruser, rnode, uuser , E_nodename,
  744.                rdfile, rdfile, everyone);
  745.    fclose(stream);
  746.  
  747.    if (SavePath != NULL)
  748.       return 1;
  749.  
  750. /*--------------------------------------------------------------------*/
  751. /*  Create the data file with the mail to send to the remote system   */
  752. /*--------------------------------------------------------------------*/
  753.  
  754.    importpath(msname, idfile, path);
  755.    mkfilename( msfile, E_spooldir, msname);
  756.  
  757.    stream = FOPEN(msfile, "w", BINARY);
  758.    if (stream == NULL )
  759.    {
  760.       printerr(msfile);
  761.       printmsg(0,
  762.                "DeliverRemote: Cannot open spool file \"%s\" for output",
  763.                 msfile);
  764.       return 0;
  765.    }
  766.  
  767.    if (!CopyData( TRUE, input , stream ))
  768.    {
  769.       remove( msfile );
  770.       return 0;
  771.    }
  772.  
  773. /*--------------------------------------------------------------------*/
  774. /*                     create local C (call) file                     */
  775. /*--------------------------------------------------------------------*/
  776.  
  777.    importpath( msname, tmfile, path);
  778.    mkfilename( msfile, E_spooldir, msname);
  779.  
  780.    stream = FOPEN(msfile, "w", TEXT);
  781.    if (stream == NULL)
  782.    {
  783.       printerr( msname );
  784.       printmsg(0, "DeliverRemote: cannot open C file %s", msfile);
  785.       return 0;
  786.    }
  787.  
  788.    fprintf(stream, send_cmd, idfile, rdfile, uuser, idfile);
  789.    fprintf(stream, send_cmd, ixfile, rxfile, uuser, ixfile);
  790.    fclose(stream);
  791.  
  792.    if (bflag[F_MULTI])        /* Deliver to multiple users at once?  */
  793.       SavePath = strdup(path);   /* Yes --> Save routing info        */
  794.  
  795.    return 1;
  796. } /* DeliverRemote */
  797.  
  798. /*--------------------------------------------------------------------*/
  799. /* C o p y D a t a                                                    */
  800. /*                                                                    */
  801. /* Copy data into its final resting spot                              */
  802. /*--------------------------------------------------------------------*/
  803.  
  804. static int CopyData( const boolean remotedelivery,
  805.                      const char *input,
  806.                      FILE *dataout)
  807. {
  808.    FILE *datain = FOPEN(input, "r", TEXT);
  809.    char buf[BUFSIZ];
  810.    int column = 0;
  811.    boolean success = TRUE;
  812.  
  813.    int (*put_string) (char *, FILE *) = (int (*)(char *, FILE *)) fputs;
  814.                               /* Assume no Kanji translation needed  */
  815.  
  816. /*--------------------------------------------------------------------*/
  817. /*                      Verify the input opened                       */
  818. /*--------------------------------------------------------------------*/
  819.  
  820.    if (datain == NULL)
  821.    {
  822.       printerr(input);
  823.       printmsg(0,"Unable to open input file \"%s\"", input);
  824.       fclose(dataout);
  825.       return 0;
  826.    } /* datain */
  827.  
  828. /*--------------------------------------------------------------------*/
  829. /*    When we do the From line, we also determine if we must          */
  830. /*    translate the data.  Note that the default is initialized to    */
  831. /*    fputs() above.                                                  */
  832. /*                                                                    */
  833. /*    If Kanji is not enabled, don't translate it                     */
  834. /*                                                                    */
  835. /*    If local mail queued for local delivery, the data is already    */
  836. /*    in Shift JIS, so don't translate it.                            */
  837. /*                                                                    */
  838. /*    If remote mail is queued for remote delivery, the data is       */
  839. /*    already in JIS 7bit, so don't translate it.                     */
  840. /*                                                                    */
  841. /*    If delivering remote mail locally, translate to Shift JIS       */
  842. /*                                                                    */
  843. /*    If delivering local mail remotely, translate to JIS 7 bit       */
  844. /*--------------------------------------------------------------------*/
  845.  
  846. /*--------------------------------------------------------------------*/
  847. /*                        Generate a FROM line                        */
  848. /*--------------------------------------------------------------------*/
  849.  
  850.    switch( (int) remoteMail * 2 + (int) remotedelivery )
  851.    {
  852.       case 3:                 /* Remote sender, remote delivery      */
  853.          strcpy( buf, fromuser );
  854.          strtok( buf, "!");   /* Get first host in list              */
  855.  
  856.          if ( equal(HostAlias( buf ), fromnode ))
  857.                               /* Host already in list?               */
  858.          {                    /* Yes --> Don't do it twice           */
  859.             fprintf(dataout, "From %s %s remote from %s\n",
  860.                      fromuser, now, E_nodename);
  861.             break;
  862.          }
  863.          else {                /* No --> Insert it                    */
  864.             fprintf(dataout, "From %s!%s %s remote from %s\n",
  865.                      fromnode, fromuser, now, E_nodename);
  866.             break;
  867.          }
  868.  
  869. /*--------------------------------------------------------------------*/
  870. /*    Note:  For the Kanji translation we re-check the                */
  871. /*    remoteDelivery flag since we do the fall through from above.    */
  872. /*--------------------------------------------------------------------*/
  873.  
  874.       case 2:                 /* Remote sender, local delivery       */
  875.          if ( bflag[ F_KANJI ] )
  876.                               /* Kanji from remote node?             */
  877.             put_string = (int (*)(char *, FILE *)) fputs_shiftjis;
  878.                               /* Yes --> Translate it                */
  879.  
  880.          fprintf(dataout, "From %s %s remote from %s\n",
  881.                   fromuser, now, fromnode);
  882.          break;
  883.  
  884.       case 1:                 /* Local sender, remote delivery       */
  885.          if ( bflag[F_KANJI]) /* Translation enabled?                */
  886.             put_string = (int (*)(char *, FILE *)) fputs_jis7bit;
  887.                               /* Translate into 7 bit Kanji          */
  888.  
  889.          column = strlen(E_domain) - 5;
  890.          if ((column > 0) && equali(&E_domain[column],".UUCP"))
  891.                               /* UUCP domain?                        */
  892.             fprintf(dataout, "From %s %s remote from %s\n",
  893.                              fromuser, now, E_nodename);
  894.                               /* Yes --> Use simple address          */
  895.          else
  896.             fprintf(dataout, "From %s!%s %s remote from %s\n",
  897.                   E_domain, fromuser, now, E_nodename);
  898.                               /* No --> Use domain address           */
  899.          break;
  900.  
  901.       case 0:                 /* Local sender, local delivery        */
  902.          fprintf(dataout, "From %s %s\n", fromuser, now);
  903.          break;
  904.  
  905.    } /* switch */
  906.  
  907. /*--------------------------------------------------------------------*/
  908. /*                       Loop to copy the data                        */
  909. /*--------------------------------------------------------------------*/
  910.  
  911.    while (fgets(buf, BUFSIZ, datain) != NULL)
  912.    {
  913.       if ((*put_string)(buf, dataout) == EOF)     /* I/O error? */
  914.       {
  915.          printerr("output");
  916.          printmsg(0,"I/O error on \"%s\"", "output");
  917.          fclose(dataout);
  918.          return 0;
  919.       } /* if */
  920.    } /* while */
  921.  
  922. /*--------------------------------------------------------------------*/
  923. /*                      Close up shop and return                      */
  924. /*--------------------------------------------------------------------*/
  925.  
  926.    if (ferror(datain))        /* Clean end of file on input?         */
  927.    {
  928.       printerr(input);
  929.       clearerr(datain);
  930.       success = FALSE;
  931.    }
  932.  
  933.    fclose(datain);
  934.    fclose(dataout);
  935.    return success;
  936. } /* CopyData */
  937.  
  938. /*--------------------------------------------------------------------*/
  939. /*    s t a t s                                                       */
  940. /*                                                                    */
  941. /*    Report size of file in message, if desired                      */
  942. /*--------------------------------------------------------------------*/
  943.  
  944. static char *stats( const char *fname )
  945. {
  946.    if (bflag[ F_COLLECTSTATS ] )
  947.    {
  948.       long size;
  949.       time_t ltime = stater(fname, &size);
  950.  
  951.       if ( ltime == -1 )
  952.       {
  953.          printerr( fname );
  954.          return "(unknown size)";
  955.       }
  956.       else {
  957.          static char buf[25];  /* "(nnnnnnn bytes) " */
  958.                                /*  ....+....+....+.. */
  959.          sprintf(buf,   "(%ld bytes) ",size );
  960.          return buf;
  961.       } /* else */
  962.    } /* if */
  963.    else
  964.       return "";              /* Pretend we were never here       */
  965.  
  966. } /* stats */
  967.